﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.AccessControl;
using System.Security.Claims;
using System.Text;
using WebCoreAPI.Config;
using WebCoreAPI.Filter;
using WebCoreAPI.Identity;

namespace WebCoreAPI.Controllers
{
    /// <summary>
    /// 使用Identity框架的 JWT
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize]
    public class JWTIdentityController : ControllerBase
    {
        private readonly UserManager<MyUser> userManager;
        private readonly RoleManager<MyRole> roleManager;
        private readonly IOptionsSnapshot<JWTOptions> jwtOptions;

        public JWTIdentityController(UserManager<MyUser> userManager, RoleManager<MyRole> roleManager, IOptionsSnapshot<JWTOptions> jwtOptions)
        {
            this.userManager = userManager;
            this.roleManager = roleManager;
            this.jwtOptions = jwtOptions;
        }

        /// <summary>
        /// Identity与 JWT 结合
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        [HttpPost]
        [UnCheckJW]
        [AllowAnonymous]
        public async Task<ActionResult<string>> IdentityLogin(string name, string pwd) 
        {
            MyUser user = await userManager.FindByNameAsync(name);
            if (user == null) return BadRequest("无此用户信息");
            if (await userManager.CheckPasswordAsync(user, pwd))
            { //登录成功了
                user.JWTVersioin++;
                await userManager.UpdateAsync(user);

                var claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()));
                claims.Add(new Claim(ClaimTypes.Name, user.UserName));
                claims.Add(new Claim(ClaimTypes.Version, user.JWTVersioin.ToString()));
                var roles= await userManager.GetRolesAsync(user);
                foreach (var role in roles)
                {
                    claims.Add(new Claim(ClaimTypes.Role,role));
                }
                //生成JWT,并返回
                DateTime expires = DateTime.Now.AddSeconds(jwtOptions.Value.ExpireSeconds);
                byte[] secBytes = Encoding.UTF8.GetBytes(jwtOptions.Value.SigningKey);
                var secKey = new SymmetricSecurityKey(secBytes);
                var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256);
                var tokenDescriptor = new JwtSecurityToken(claims: claims, expires: expires, signingCredentials: credentials);
                return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);
            }
            return BadRequest("登录失败，请重试");
        }

        /// <summary>
        /// 只有登录后才可以访问该Action
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<String> GetUseInfo()
        {
            string id = this.User.FindFirstValue(ClaimTypes.NameIdentifier);
            string userName = this.User.FindFirstValue(ClaimTypes.Name);
            IEnumerable<Claim> claims= this.User.FindAll(ClaimTypes.Role);
            return Ok($"id={id},userName={userName},roleNames ={claims.First().Value}");
        }

        [HttpPost]
        [UnCheckJW]
        [AllowAnonymous]
        public async Task<ActionResult<string>> AddUserInfo(MyUser user) {
            if (ModelState.IsValid)
            {
                await Console.Out.WriteLineAsync("通过验证");
            }
            else {
                await Console.Out.WriteLineAsync("没有通过验证");
            }
            //IdentityResult result = await userManager.CreateAsync(user, "123456");
            //if (result.Succeeded) return BadRequest("创建用户 失败");
            return Ok("创建成功");
        }

    }
}
